/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: worker_descriptor.hpp
 */

#ifndef _WORKER_DESCRIPTOR_HPP_
#define _WORKER_DESCRIPTOR_HPP_

#include <iostream>
#include <string>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include "address.hpp"
#include "performance_index.hpp"

//-----------------------------------------------------------------------------
// Enum, struct, aliases
namespace middleware {
/*!
 * Describing worker capabilities.
 */
typedef struct {
	friend class boost::serialization::access;
	/*!
	 * BOOST serialization function.
	 */
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & capab_cpu_mhz;
		ar & capab_ram_mb;
		ar & capab_core_num;
		ar & capab_cpu_num;
		ar & capab_hops;
		ar & capab_bandwidth;
	}
	/*!
	 * Members
	 */
	double capab_cpu_mhz; /* CPU MHz */
	double capab_ram_mb; /* RAM in MegaBytes */
	unsigned int capab_core_num; /* Number of cores per processor */
	unsigned int capab_cpu_num; /* Number of processors */
	unsigned int capab_hops; /* INET hop distance */
	double capab_bandwidth; /* Bandwidth in KBit/s */
} WorkerCapabilities;
/*!
 * Type for worker load (number of pending tasks).
 */
typedef unsigned int WorkerLoad;
}
//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Standard capabilities.
 */
const WorkerCapabilities kStdWorkerCapab = {
		800.0 /* 800 Mhz CPU */,
		512.0 /* 512 MB RAM */,
		2 /* Intel 2-Core */,
		1 /* One CPU */,
		1 /* 5 hops: almost a great local network */,
		5000.0 /* 5 Mbit/s */
};
/*!
 * When not specified, a worker has this performance.
 */
const WorkerCapabilities kDefWorkerCapab = {
		0.0 /* Mhz CPU */,
		0.0 /* MB RAM */,
		0 /* Cores */,
		0 /* CPUs */,
		0 /* Hops: almost a great local network */,
		0.0 /* Mbit/s */
};
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
class WorkerDescriptor {
	friend class Worker;
public:
	/*!
	 * Sets invalid port on local address and default capabilities.
	 */
	WorkerDescriptor();
	/*!
	 * Defines default capabilities with the specified address.
	 */
	explicit WorkerDescriptor(Address addr);
	/*!
	 * Assigns capabilities and address.
	 */
	WorkerDescriptor(Address addr, WorkerCapabilities capab);
	/*!
	 * Copy constructor.
	 */
	WorkerDescriptor(const WorkerDescriptor& wdesc);
	/*!
	 * Destructor.
	 */
	~WorkerDescriptor();
	/*!
	 * Gets the load/status of the worker associated to this descriptor.
	 */
	WorkerLoad get_status() const {
		return this->_status;
	}
	/*!
	 * Sets the load/status of the worker associated to this descriptor.
	 */
	void set_status(WorkerLoad status) {
		this->_status = status;
	}
	/*!
	 * Gets capabilities.
	 */
	WorkerCapabilities get_capabilities() const {
		return this->_capabilities;
	}
	/*!
	 * Sets capabilities.
	 */
	void set_capabilities(WorkerCapabilities capab) {
		this->_capabilities = capab;
	}
	/*!
	 * Gets the address.
	 */
	Address get_address() const {
		return this->_address;
	}
	/*!
	 * Sets the address.
	 */
	void set_address(Address addr) {
		this->_address = addr;
	}
	/*!
	 * Gets the current PI.
	 */
	calculus::PIType PI() const;
	/*!
	 * In order to see if a descriptor is changed, let's overload equality
	 * operator.
	 */
	bool operator==(const WorkerDescriptor& wdesc) const;
	bool operator!=(const WorkerDescriptor& wdesc) const;
private:
	friend class boost::serialization::access;
	/*!
	 * BOOST serialization function.
	 */
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & _address;
		ar & _capabilities;
		ar & _status;
	}
	/*!
	 * Address.
	 */
	Address _address;
	/*!
	 * Capabilities of this worker.
	 */
	WorkerCapabilities _capabilities;
	/*!
	 * Indicates the load actually sustained by the worker. From now on, we'll
	 * intend status = load. If load is 0 ==> status is free. If load > 0 ==>
	 * status is not free.
	 */
	WorkerLoad _status;
};
} /* middleware */

#endif
